import { AudioClip, AudioSource, find, isValid, Node } from "cc";

export class BCAudioMgr {
	private static m_instance: BCAudioMgr = null;

	private m_soundSwitch: boolean = true;		//音效
	get soundSwitch(): boolean{
		return this.m_soundSwitch;
	}
	set soundSwitch(status: boolean){
		this.m_soundSwitch = status;
		this.saveSettings();
	}

	private m_musicSwitch: boolean = true;		//音乐
	get musicSwitch(): boolean {
		return this.m_musicSwitch;
	}
	set musicSwitch(status: boolean) {
		this.m_musicSwitch = status;
		if (status) {
			this.resume();
		} else {
			this.stop();
		}
		this.saveSettings();
	}

	private m_micSwitch: boolean = true;		//麦克风
	get micSwitch(): boolean {
		return this.m_micSwitch;
	}
	set micSwitch(status: boolean) {
		this.m_micSwitch = status;
		this.saveSettings();
	}

	private m_audioSourceCache: Map<string, AudioSource> = new Map<string, AudioSource>();		//音效控制器列表，key为调用改音效节点的uuid

	private constructor() {
		const sysSettingData = localStorage.getItem("game_sys_setting");
		if (sysSettingData && sysSettingData.length != 0){
			try{
				const sysSetting = JSON.parse(sysSettingData);
				this.m_musicSwitch = sysSetting['music'];
				if (typeof (this.m_musicSwitch) == 'undefined') {
					this.m_musicSwitch = true;
				}
				this.m_soundSwitch = sysSetting['sound'];
				if (typeof (this.m_soundSwitch) == 'undefined') {
					this.m_soundSwitch = true;
				}
				this.m_micSwitch = sysSetting['mic'];
				if (typeof (this.m_micSwitch) == 'undefined'){
					this.m_micSwitch = true;
				}
			} catch(e){}
		}
	}

	static get instance(): BCAudioMgr {
		if (!this.m_instance) {
			this.m_instance = new BCAudioMgr();
		}
		return this.m_instance;
	}

	private saveSettings(){
		localStorage.setItem("game_sys_setting", JSON.stringify({
			music: this.m_musicSwitch,
			sound: this.m_soundSwitch,
			mic: this.m_micSwitch
		}));
	}

	/**
	 * 播放长音频（bgm或长音效）
	 */
	playMusic(clip: AudioClip, loop: boolean, node?: Node, startCb?: () => void, finishCb?: () => void) {
		if (!clip) {
			return
		}
		if (!node) {
			node = find("Canvas");
		}
		const audioSwitch = loop ? this.m_musicSwitch : this.m_soundSwitch;				//不循环播放的音频归为音效，循环播放的才归为背景音乐
		let audioSource: AudioSource = node.getComponent(AudioSource);
		if (!audioSource) {
			audioSource = node.addComponent(AudioSource);
		}
		this.m_audioSourceCache.set(node.uuid, audioSource);
		audioSource.clip = clip;
		audioSource.loop = loop;
		startCb && node.on(AudioSource.EventType.STARTED, () => {
			startCb();
			node.off(AudioSource.EventType.STARTED, () => { }, this);
		}, this);
		finishCb && node.on(AudioSource.EventType.ENDED, () => {
			finishCb();
			node.off(AudioSource.EventType.ENDED, () => { }, this);
		}, this);
		if (!audioSwitch) {
			return;
		}
		audioSource.play();
	}

	/**
	 * 暂停节点声音
	 * 如果节点为null，则默认暂停场景所有声音
	 */
	pause(node?: Node) {
		if (node) {
			const audioSource = this.m_audioSourceCache.get(node.uuid);
			audioSource && audioSource.pause();
			return;
		}

		//遍历缓存中所有audioSource并暂停
		this.m_audioSourceCache.forEach((audioSource, uuid) => {
			if (audioSource && isValid(audioSource)) {
				audioSource.pause();
			} else {
				this.m_audioSourceCache.delete(uuid);				//清除无效AudioSource缓存
			}
		});
	}

	/**
	 * 恢复节点声音
	 * 如果节点为null，则默认恢复场景所有声音
	 */
	resume(node?: Node) {
		if (node) {
			const audioSource = this.m_audioSourceCache.get(node.uuid);
			audioSource && audioSource.play();
			return;
		}

		//遍历缓存中所有audioSource并恢复播放
		this.m_audioSourceCache.forEach((audioSource, uuid) => {
			if (audioSource && isValid(audioSource)) {
				audioSource.play();
			} else {
				this.m_audioSourceCache.delete(uuid);				//清除无效AudioSource缓存
			}
		});
	}

	/**
	 * 停止节点声音
	 * 如果节点为null，则默认停止场景所有声音
	 */
	stop(node?: Node) {
		if (node) {
			const audioSource = this.m_audioSourceCache.get(node.uuid);
			audioSource && audioSource.stop();
			return;
		}

		//遍历缓存中所有audioSource并停止播放
		this.m_audioSourceCache.forEach((audioSource, uuid)=>{
			if (audioSource && isValid(audioSource)) {
				audioSource.stop();
			} else {
				this.m_audioSourceCache.delete(uuid);				//清除无效AudioSource缓存
			}
		});
	}

	playSound(clip: AudioClip, node?: Node) {
		if (!this.m_soundSwitch) {
			return;
		}

		if (!clip) {
			return;
		}

		if (!node) {
			node = find("Canvas");
		}
		let audioSource: AudioSource = node.getComponent(AudioSource);
		if (!audioSource) {
			audioSource = node.addComponent(AudioSource);
		}
		audioSource.loop = false;
		audioSource.playOneShot(clip);
	}
}

